package com.clusterswisdom.horn.api.tmall.action.eticket;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.clusterswisdom.horn.api.db.DbUtil;
import com.clusterswisdom.horn.api.push.PushDataUtil;
import com.clusterswisdom.horn.api.tmall.TmallInstance;

@WebServlet(name="eticketServlet", urlPatterns="/eticket.action")
public class SendCodeServlet extends HttpServlet implements Serializable {
	
	private static final long serialVersionUID = 5825898085766478541L;
	
	public static final String CODE = "23afbdc08a3a38e44462c1ab04e16d91";
	
	public static final String ETICKET = "eticket";
	
	public static final String PARAM_METHOD = "method";
	
	public static final String PARAM_SIGN = "sign";
	
	public static final String METHOD_SEND = "send";

	public static final String METHOD_RESEND = "resend";
	
	private Logger log = LoggerFactory.getLogger(SendCodeServlet.class);
	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		log.debug("get SendCodeServlet " + request.getParameterMap().toString());
		
		if (METHOD_SEND.equals(getMethod(request))) {
			JSONObject param = getRequestParam(request);
			String channel = TmallInstance.getInstance().getConfig().getChannel();
			Long logId = DbUtil.getUtil().saveLog(channel, ETICKET, ETICKET, JSON.toJSONString(param));
			
			if (validateRequest(request)) {
				try {
					String result = PushDataUtil.getUtil().pushData("${pushServer}/tmall/notify.action", param);
					DbUtil.getUtil().logResult(logId, "成功", result);
					sendTmallResponse(response, true);
					
				} catch (Exception e) {
					e.printStackTrace();
					DbUtil.getUtil().logResult(logId, "exception", e.getMessage());
					sendTmallResponse(response, false);
				}
				
			} else {
				DbUtil.getUtil().logResult(logId, "validate fault", "validate fault");
				sendTmallResponse(response, false);
				
			}
		}
		
		sendTmallResponse(response, true);
	}
	
	private void sendTmallResponse(HttpServletResponse response, boolean success) throws IOException {
		JSONObject result = new JSONObject();
		result.put("code", success ? 200 : 401);
		
		response.getWriter().write(JSON.toJSONString(result));
		response.getWriter().flush();
		response.flushBuffer();
	}
	
	private String getMethod(HttpServletRequest request) {
		return request.getParameter(PARAM_METHOD);
	}
	
	private JSONObject getRequestParam(HttpServletRequest request) {
		JSONObject param = new JSONObject();
		Enumeration<String> names = request.getParameterNames();
		while (names.hasMoreElements()) {
			String key = names.nextElement();
			param.put(key, request.getParameter(key));
		}
		
		return param;
	}
	

	private boolean validateRequest(HttpServletRequest request) {
		List<String> paramList = getParamNames(request);
		
		StringBuilder content = new StringBuilder(CODE);
		for (String param : paramList) {
			content.append(param).append(request.getParameter(param));
		}
		
		return getMd5Value(content.toString()).equals(request.getParameter(PARAM_SIGN));
	}
	
	private String getMd5Value(String value) {
		return DigestUtils.md5Hex(value).toUpperCase();
	}
	
	private List<String> getParamNames(HttpServletRequest request) {
		List<String> paramNameList = new ArrayList<String>();
		
		Enumeration<String> names = request.getParameterNames();
		while (names.hasMoreElements()) {
			String key = names.nextElement();
			String value = request.getParameter(key);
			if (!key.equals(PARAM_SIGN) && value != null && value.trim().length() > 0) {
				paramNameList.add(key);
			}
		}
		
		Collections.sort(paramNameList, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.compareTo(o2);
			}
		});
		
		return paramNameList;
	}
}
